﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using RedBit.OAuthLibrary;

namespace TradeMeSDK
{
    public class TradeMeCatalog
    {
        //private readonly PersistentDataStore _store = new PersistentDataStore();
        private readonly UserDataStore _store = new UserDataStore();

        private List<Locality> _localities;
        private List<Locality> _areas;
        private Category _rootCategory;
        private List<JobCategory> _jobCategories;

        public List<Locality> Localities
        {
            get
            {
                if ((_localities == null) && _store.Exists("Localities"))
                    _localities = _store.Restore<List<Locality>>("Localities");
                return _localities;
            }
            private set
            {
                _localities = value;
                _store.Backup("Localities", value);
            }
        }

        public List<Locality> Areas
        {
            get
            {
                if ((_areas == null) && _store.Exists("Areas"))
                    _areas = _store.Restore<List<Locality>>("Areas");
                return _areas;
            }
            private set
            {
                _areas = value;
                _store.Backup("Areas", value);
            }
        }

        public Category RootCategory
        {
            get 
            {
                if ((_rootCategory == null) && _store.Exists("RootCategory"))
                    _rootCategory = _store.Restore<Category>("RootCategory");
                return _rootCategory; 
            }
            private set
            {
                _rootCategory = value;
                _store.Backup("RootCategory", value);
            }
        }

        public List<JobCategory> JobCategories
        {
            get
            {
                if ((_jobCategories == null) && _store.Exists("JobCategories"))
                    _jobCategories = _store.Restore<List<JobCategory>>("JobCategories");
                return _jobCategories;
            }
            set
            {
                _jobCategories = value;
                _store.Backup("JobCategories", value);
            }
        }


        public void DownloadLocalities(Action<BaseEventArgs<List<Locality>>> callback)
        {
            WebHelper.DownloadAndParse<List<Locality>>(TradeMeConstants.LocalitiesUrl,
                result =>
                {
                    if (!result.IsError)
                        Localities = result.Response;
                    callback(result);
                });
        }

        public void DownloadAreas(Action<BaseEventArgs<List<Locality>>> callback)
        {
            WebHelper.DownloadAndParse<List<Locality>>(TradeMeConstants.AreasUrl,
                result =>
                {
                    if (!result.IsError)
                    {
                        // TradeMe currently do not send NorthIsland and SouthIsland
                        if (result.Response.SingleOrDefault(l => l.LocalityId == 50) == null)
                            result.Response.Insert(0, new Locality { LocalityId = 50, Name = "North Island" });
                        if (result.Response.SingleOrDefault(l => l.LocalityId == 60) == null)
                            result.Response.Insert(1, new Locality { LocalityId = 60, Name = "South Island" });
                        Areas = result.Response;
                    }
                    callback(result);
                });
        }

        public void DownloadRootCategory(Action<BaseEventArgs<Category>> callback)
        {
            WebHelper.DownloadAndParse<Category>(TradeMeConstants.CategoriesUrl, 
                result =>
                    {
                        if (!result.IsError)
                            RootCategory = result.Response;
                        callback(result);
                    });
        }

        public void DownloadJobCategories(Action<BaseEventArgs<List<JobCategory>>> callback)
        {
            WebHelper.DownloadAndParse<List<JobCategory>>(TradeMeConstants.JobCategoriesUrl,
                result =>
                    {
                        if (!result.IsError)
                            JobCategories = result.Response;
                        callback(result);
                    });
        }

        public void DownloadSubCategory(string categoryNumber, Action<BaseEventArgs<Category>> callback)
        {
            string url = TradeMeConstants.SubCategoryUrl + categoryNumber + ".json";
            WebHelper.DownloadAndParse(url, callback);
        }

        public void DownloadUsedCarsCategories(Action<BaseEventArgs<Category>> callback)
        {
            DownloadSubCategory("UsedCars", callback);
        }

        public void DownloadMotorBikeCategories(Action<BaseEventArgs<Category>> callback)
        {
            DownloadSubCategory("MotorBikes", callback);
        }

        public bool IsDownloaded
        {
            get
            {
                if ((Localities == null) || (Areas == null) || (JobCategories == null) || (RootCategory == null))
                    return false;
                return true;
            }
        }

        public event EventHandler DownloadCompleted;
        public void InvokeDownloadCompleted(EventArgs e)
        {
            EventHandler handler = DownloadCompleted;
            if (handler != null) handler(this, e);
        }


        private AutoResetEvent _localitiesResetEvent = new AutoResetEvent(false);
        private AutoResetEvent _areasResetEvent = new AutoResetEvent(false);
        private AutoResetEvent _jobCategoriesResetEvent = new AutoResetEvent(false);
        private AutoResetEvent _rootCategoryResetEvent = new AutoResetEvent(false);

        public void Download()
        {
            ThreadPool.QueueUserWorkItem(
                state =>
                    {
                        DownloadLocalities(result => _localitiesResetEvent.Set());
                        DownloadAreas(result => _areasResetEvent.Set());
                        DownloadJobCategories(result => _jobCategoriesResetEvent.Set());
                        DownloadRootCategory(result => _rootCategoryResetEvent.Set());

                        _localitiesResetEvent.WaitOne();
                        _areasResetEvent.WaitOne();
                        _jobCategoriesResetEvent.WaitOne();
                        _rootCategoryResetEvent.WaitOne();

                        InvokeDownloadCompleted(new EventArgs());
                    });
        }

        public void Reset()
        {
            _store.Delete("Localities");
            _store.Delete("Areas");
            _store.Delete("RootCategory");
            _store.Delete("JobCategories");
        }
    }
}
